﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Bot.Domain.Report
{
    public class ReportExportData 
    {
        /*
         * 备注
         * 参数名称统一
         * action对应报表类型
         * group对应搜索条件的组织级别 site/department/operator
         * timeUnit对应搜索条件的时间单位级别  day/week/month
         * dateRange对应搜索条件中的时间下拉空间  10种时间
         * startDate,endDate对应自定义时间中的起始和结束值(取界面显示的字符串)
         */

        public static string ExportReport(SearchCriteria search, NewExportCSVData exportdata)
        {
            string path = "";

            //NewExportCSVData exportdata = new NewExportCSVData(string.Empty, new List<NewCSVColumn>(), new DataTable());
            try
            {
                //var search = SetupSearch();
                switch (search.action)
                {
                    case EnumNewReportActionType.RealTime:
                        break;
                    case EnumNewReportActionType.ChatVolume:
                        //exportdata = ChatVolumeWrap.GetExprotData(search);
                        break;
                    case EnumNewReportActionType.ChatSource:
                        //exportdata = ChatSourceWrap.GetExprotData(search);
                        break;
                    case EnumNewReportActionType.Queue:
                        //exportdata = QueueWrap.GetExprotData(search);
                        break;
                    case EnumNewReportActionType.WaitTime:
                        //exportdata = WaitTimeWrap.GetExprotData(search);
                        break;
                    case EnumNewReportActionType.ChatTransfer:
                        //exportdata = ChatTransferWrap.GetExprotData(search);
                        break;
                    case EnumNewReportActionType.Availability:
                        //var data = AvailabilityProcess.GetOperatorStatusLogs(search);
                        //exportdata = AvailabilityWrap.GetExportData(search, data);
                        break;
                    case EnumNewReportActionType.Workload:
                        //exportdata = WorkLoadWrap.GetExprotData(search);
                        break;
                    case EnumNewReportActionType.Efficiency:
                        //exportdata = EfficiencyWrap.GetExprotData(search);
                        break;
                    case EnumNewReportActionType.Rating:
                        //exportdata = RatingWrap.GetExprotData(search);
                        break;
                    case EnumNewReportActionType.chatbot:
                        switch (search.dimensionType)
                        {
                            case EnumDimensionType.ChatbotChats:
                                //exportdata = ChatsWrap.GetExprotData(search);
                                break;
                            case EnumDimensionType.ChatbotAnswers:
                                //exportdata = ChatbotAnswersWrap.GetExprotData(search);
                                break;
                            case EnumDimensionType.ChatbotHightFidenceAnswers:
                                //exportdata = ChatbotHighConfidenceAnswerWrap.GetExprotData(search);
                                break;
                        }
                        break;
                    case EnumNewReportActionType.PostChatSurvey:
                        //exportdata = SurveyWrap.GetExprotData(search, EnumFormType.PostChat);
                        break;
                    case EnumNewReportActionType.PreChatSurvey:
                        //exportdata = SurveyWrap.GetExprotData(search, EnumFormType.PreChat);
                        break;
                    case EnumNewReportActionType.Wrapup:
                        //exportdata = WrapUpSurveyWrap.GetExprotData(search);
                        break;
                    case EnumNewReportActionType.ManualInvitation:
                        //exportdata = ManualInvitationWrap.GetExprotData(search);
                        break;
                    case EnumNewReportActionType.AutoInvitation:
                        //exportdata = AutoInvitationWrap.GetExprotData(search);
                        break;
                    case EnumNewReportActionType.OfflineMessage:
                        //exportdata = OfflineMessageWrap.GetExprotData(search);
                        break;
                    case EnumNewReportActionType.CannedMessage:
                        //exportdata = CannedMessageWrap.GetExprotData(search);
                        break;
                    case EnumNewReportActionType.TrafficSource:
                        break;
                    case EnumNewReportActionType.Performance:
                        //exportdata = PerformanceWrap.GetExprotData(search);
                        break;
                    default:
                        break;
                }
                double clinetOffset = CommonHelper.GetClientTimeZoneOffSet();
                string dateNow = DateTime.UtcNow.AddMinutes(-clinetOffset).ToString("yyyyMMddHHmmssfff");
                bool IfTime = LiveChatConfig.IfCanSelectHourlyMinute(search.siteId);
                switch (search.dimensionType)
                {
                    case EnumDimensionType.ByTime:
                        exportdata.Title = exportdata.Title + "Details of ";
                        if (search.filterType == EnumFilterType.Site)
                        {
                            exportdata.Title = exportdata.Title + search.filterType.ToString() + " " + GetDimensionName(search.dimensionType);
                        }
                        else if (search.filterType == EnumFilterType.VisitorSegment)
                        {
                            exportdata.Title = exportdata.Title + "Visitor Segment " + search.filterStr + " " + GetDimensionName(search.dimensionType);
                        }
                        else
                        {
                            exportdata.Title = exportdata.Title + search.filterType.ToString() + " " + search.filterStr + " " + GetDimensionName(search.dimensionType);
                        }
                        break;
                    case EnumDimensionType.ByDepartment:
                    case EnumDimensionType.ByAgent:
                    case EnumDimensionType.ByCampaign:
                    case EnumDimensionType.ByVisitorSegment:
                    case EnumDimensionType.ByInvitation:
                        exportdata.Title = exportdata.Title + "Details " + GetDimensionName(search.dimensionType);
                        break;
                    case EnumDimensionType.RequestPage:
                        exportdata.Title = exportdata.Title + "Details by " + GetDimensionName(search.dimensionType);
                        break;
                    case EnumDimensionType.ChangeLog:
                        if (search.filterType == EnumFilterType.Agent)
                        {
                            exportdata.Title = exportdata.Title + GetDimensionName(search.dimensionType) + " of " + search.filterType.ToString() + " " + search.filterStr + " ";
                        }
                        break;
                    case EnumDimensionType.Survey:
                        if (search.filterStr.Equals("All Campaigns"))
                        {
                            exportdata.Title = exportdata.Title + search.filterStr + " ";
                        }
                        else
                        {
                            exportdata.Title = exportdata.Title + search.filterType.ToString() + " " + search.filterStr + " ";
                        }
                        break;
                    case EnumDimensionType.ChatbotChats:
                    case EnumDimensionType.ChatbotAnswers:
                    case EnumDimensionType.ChatbotHightFidenceAnswers:
                        if (search.filterType == EnumFilterType.Campaign)
                        {
                            exportdata.Title = exportdata.Title + search.filterType.ToString() + " " + search.filterStr + " ";
                        }
                        else
                        {
                            exportdata.Title = exportdata.Title + search.filterType.ToString();
                        }

                        break;
                    default:
                        exportdata.Title = exportdata.Title + search.filterType.ToString() + " " + search.filterStr + " ";
                        break;

                }
                if (IfTime)
                {
                    if (search.dateRange == EnumDateRangeType.Custom)
                    {
                        exportdata.TimeRange = search.startDate.ToString("MM/dd/yyyy HH:mm") + " ~ " + search.endDate.AddMilliseconds(-1).ToString("MM/dd/yyyy HH:mm");
                    }
                    else
                    {
                        exportdata.TimeRange = search.startDate.ToString("MM/dd/yyyy HH:mm") + " ~ " + search.endDate.AddMinutes(-1).ToString("MM/dd/yyyy") + " 24:00";
                    }
                }
                else
                {
                    exportdata.TimeRange = search.startDate.ToString("MM/dd/yyyy") + " ~ " + search.endDate.AddDays(-1).ToString("MM/dd/yyyy");
                }

                exportdata.DisplayedBy = GetDisplayByName(search.timeUnit);

                if (search.action != EnumNewReportActionType.CannedMessage && search.action != EnumNewReportActionType.PostChatSurvey
                    && search.action != EnumNewReportActionType.PreChatSurvey
                    && search.action != EnumNewReportActionType.ChatbotChats
                    && search.action != EnumNewReportActionType.ChatbotResponse
                    && search.action != EnumNewReportActionType.ChatbotHighConfidenceResponse
                    && search.action != EnumNewReportActionType.ChatbotRating
                    && search.action != EnumNewReportActionType.ChatbotAgent)
                {
                    exportdata.name = GetActionName(search.action) + "_" + search.dimensionType.ToString() + "_" + dateNow;
                }
                else
                {
                    exportdata.name = GetActionName(search.action) + "_" + dateNow;
                }

                //增加附属信息
                DataTable table = exportdata.source.Clone();
                table.Rows.Add(string.Format("Report:{0} {1}", exportdata.Title, channelConvert(search.dimensionType, search.channel)));
                table.Rows.Add(string.Format("Time Range:{0}", exportdata.TimeRange));
                table.Rows.Add(string.Format("Display by:{0}", exportdata.DisplayedBy));
                string[] cols = new string[exportdata.columns.Count];
                int idx = 0;
                foreach (NewCSVColumn column in exportdata.columns)
                {
                    cols[idx] = column.header;
                    idx++;
                }
                table.Rows.Add(cols);
                table.Merge(exportdata.source);
                exportdata.source = table;
                //LiveChatNewReportExportDataHelper.ExportToCSV(Response, exportdata, search.dimensionType);
                path = SaveReport(search, exportdata);
            }
            catch (Exception exp)
            {
                LogHelper.WriteExceptionLog(exp);
                throw exp;               
            }

            return path;
        }

      static  string channelConvert(EnumDimensionType enumDimensionType, string channel)
        {
            
            string channelString = "";
            if (!string.IsNullOrEmpty(channel))
            {
                if (channel == "All Channels")
                {
                    channelString = "in All Channels";
                }
                else
                {
                    channelString = $"in {channel}";
                }
            }
           
            //switch (enumDimensionType)
            //{
            //    case EnumDimensionType.ByTime:
            //        //channel = "by Time"; 
            //        break;
            //    //case EnumDimensionType.AllChannel:
            //    //    channel = "in All Channels";
            //    //    break;
            //    //case EnumDimensionType.DefaultChannel:
            //    //    channel = "in Default";
            //    //    break;
            //    //case EnumDimensionType.LivechatChannel:
            //    //    channel = "in Live Chat";
            //    //    break;
            //    //case EnumDimensionType.FacebookChannel:
            //    //    channel = "in Facebook";
            //    //    break;
            //    //case EnumDimensionType.TwitterChannel:
            //    //    channel = "in Twitter";
            //    //    break;
            //}
            return channelString;
        }
        //public static SearchCriteria SetupSearch()
        //{
        //    //string str = QueryStringHelper.CheckAndGetQueryString("SearchCriteria");

        //    SearchCriteria search = new SearchCriteria();
        //    search.action = (EnumNewReportActionType)QueryStringHelper.CheckAndGetQueryStringIntValue("action");
        //    search.categoryId = QueryStringHelper.CheckAndGetQueryStringIntValue("categoryId");
        //    search.codePlanId = QueryStringHelper.CheckAndGetQueryStringIntValue("codePlanId");
        //    search.dateFormat = QueryStringHelper.CheckAndGetQueryString("dateFormat");
        //    search.dateRange = (EnumDateRangeType)QueryStringHelper.CheckAndGetQueryStringIntValue("dateRange");
        //    search.departmentId = QueryStringHelper.CheckAndGetQueryStringIntValue("departmentId");
        //    search.dimensionType = (EnumDimensionType)QueryStringHelper.CheckAndGetQueryStringIntValue("dimensionType");
        //    search.filterStr = QueryStringHelper.CheckAndGetQueryString("filterStr");
        //    search.filterType = (EnumFilterType)QueryStringHelper.CheckAndGetQueryStringIntValue("filterType");
        //    search.operatorId = QueryStringHelper.CheckAndGetQueryStringIntValue("operatorId");
        //    search.segmentId = QueryStringHelper.CheckAndGetQueryStringIntValue("segmentId");
        //    search.siteId = QueryStringHelper.CheckAndGetQueryStringIntValue("siteId");
        //    search.timeUnit = (EnumTimeIntervalType)QueryStringHelper.CheckAndGetQueryStringIntValue("timeUnit");
        //    search.ifWrapUpAdvanced = Boolean.Parse(QueryStringHelper.CheckAndGetQueryString("ifWrapUpAdvanced"));

        //    if (search.dateRange == EnumDateRangeType.Custom)
        //    {
        //        search.startDate = JsonConvert.DeserializeObject<DateTime>(QueryStringHelper.CheckAndGetQueryString("startDate"));
        //        search.endDate = JsonConvert.DeserializeObject<DateTime>(QueryStringHelper.CheckAndGetQueryString("endDate"));
        //    }

        //    CheckAuth(search.siteId);
        //    SetupSearchCriteria(search);
        //    CheckSearchCriteriaDate(search);

        //    //SetDateTimeRangeCookie(search);
        //    return search;
        //}

        private static string GetDisplayByName(EnumTimeIntervalType type)
        {
            string result = string.Empty;
            switch (type)
            {
                case EnumTimeIntervalType.Hourly:
                    result = "Hour";
                    break;
                case EnumTimeIntervalType.Daily:
                    result = "Day";
                    break;
                case EnumTimeIntervalType.Weekly:
                    result = "Week";
                    break;
                case EnumTimeIntervalType.Monthly:
                    result = "Month";
                    break;
                case EnumTimeIntervalType.Distribution24_7Hour:
                    result = "24/7 Distribution";
                    break;
                case EnumTimeIntervalType.Distribution48HalfHour:
                    result = "Half-Hour Distribution";
                    break;
            }
            return result;
        }

        private static string GetDimensionName(EnumDimensionType type)
        {
            string str = type.ToString();
            switch (type)
            {
                case EnumDimensionType.ByTime:
                    str = "by Time";
                    break;
                case EnumDimensionType.ByDepartment:
                    str = "by Department";
                    break;
                case EnumDimensionType.ByAgent:
                    str = "by Agent";
                    break;
                case EnumDimensionType.ByCampaign:
                    str = "by Campaign";
                    break;
                case EnumDimensionType.ByVisitorSegment:
                    str = "by Visitor Segment";
                    break;
                case EnumDimensionType.RequestPage:
                    str = "Request Page";
                    break;
                case EnumDimensionType.ChangeLog:
                    str = "Change Log";
                    break;
                case EnumDimensionType.Survey:
                    break;
                case EnumDimensionType.ByInvitation:
                    str = "by Invitation";
                    break;
                default:
                    break;
            }
            return str;
        }

        private static string GetActionName(EnumNewReportActionType type)
        {
            string str = type.ToString();

            switch (type)
            {
                case EnumNewReportActionType.Wrapup:
                    str = "Wrap-Up";
                    break;
                case EnumNewReportActionType.Performance:
                    str = "AgentPerformance";
                    break;
                case EnumNewReportActionType.PreChatSurvey:
                    str = "Pre-ChatSurvey";
                    break;
                case EnumNewReportActionType.PostChatSurvey:
                    str = "PostChatSurvey";
                    break;
                case EnumNewReportActionType.ChatbotChats:
                    str = "Bot Chats";
                    break;
                case EnumNewReportActionType.ChatbotResponse:
                    str = "Bot Answers";
                    break;
                case EnumNewReportActionType.ChatbotHighConfidenceResponse:
                    str = "Bot High Confidence Answers";
                    break;
                case EnumNewReportActionType.ChatbotRating:
                    str = "Bot Rating";
                    break;
                case EnumNewReportActionType.ChatbotAgent:
                    str = "Bot Bot_Agent";
                    break;
                case EnumNewReportActionType.UsageDetailsByIntent:
                    str = "UsageDetailsByIntents";
                    break;
            }
            return str;
        }

        private static void SetupSearchCriteria(SearchCriteria search)
        {
            DateTime startDate, endDate;
            DateTime localNow = DateTimeHelper.LocalNow();
            DateTime localDate = localNow.Date;

            string format = DateTimeHelper.GetDateFormatFromSession();
            search.dateFormat = format;

            switch (search.dateRange)
            {
                case EnumDateRangeType.Today:
                    startDate = localDate;
                    endDate = startDate.AddDays(1);
                    break;
                case EnumDateRangeType.Yesterday:
                    startDate = localDate.AddDays(-1);
                    endDate = localDate;
                    break;
                case EnumDateRangeType.ThisWeek:
                    startDate = localDate.AddDays(-(int)localDate.DayOfWeek);
                    endDate = localDate.AddDays(1);
                    break;
                case EnumDateRangeType.LastWeek:
                    endDate = localDate.AddDays(-(int)localDate.DayOfWeek);
                    startDate = endDate.AddDays(-7);
                    break;
                case EnumDateRangeType.Last7Days:
                    endDate = localDate;
                    startDate = endDate.AddDays(-7);
                    break;
                case EnumDateRangeType.Last14Days:
                    endDate = localDate;
                    startDate = endDate.AddDays(-14);
                    break;
                case EnumDateRangeType.ThisMonth:
                    startDate = new DateTime(localDate.Year, localDate.Month, 1);
                    endDate = localDate.AddDays(1);
                    break;
                case EnumDateRangeType.Last30Days:
                    endDate = localDate;
                    startDate = endDate.AddDays(-30);
                    break;
                case EnumDateRangeType.LastMonth:
                    DateTime lastMonth = localDate.AddMonths(-1);
                    startDate = new DateTime(lastMonth.Year, lastMonth.Month, 1);
                    endDate = new DateTime(localDate.Year, localDate.Month, 1);
                    break;
                case EnumDateRangeType.Custom:
                    startDate = search.startDate;
                    endDate = search.endDate;
                    break;
                case EnumDateRangeType.SevenDays:
                    endDate = localDate.AddDays(1);
                    startDate = endDate.AddDays(-7);
                    break;
                default:
                    throw new Exception("unknown date range:" + search.dateRange);
            }

            search.startDate = startDate;
            search.endDate = endDate;

            search.utcStartDate = DateTimeHelper.LocalToUTC(search.startDate);
            search.utcEndDate = DateTimeHelper.LocalToUTC(search.endDate);

            //if (search.utcEndDate > DateTime.UtcNow)
            //{
            //    search.utcEndDate = DateTime.UtcNow.AddMinutes(1);
            //    search.endDate = DateTimeHelper.UTCToLocal(search.utcEndDate);
            //}
        }

        private static void CheckAuth(int siteId)
        {
            //int currentOperatorId = SessionHelper.GetSessionValue_CurrentOperatorId();
            //if (currentOperatorId <= 0)
            //{
            //    throw (new Exception("Session Time Out"));
            //}

            //CheckPermissionHelper.CheckPermission(EnumOperatorPermission.LiveChat_ViewReport, Convert.ToInt16(EnumMasterMenuType.enumReport), siteId, currentOperatorId);
        }

        private static void CheckSearchCriteriaDate(SearchCriteria search)
        {
            CheckDate(search.startDate, search.endDate);
            switch (search.timeUnit)
            {
                case EnumTimeIntervalType.Hourly:
                    if (search.startDate.AddMonths(1) < search.endDate)
                        ExceptionHelper.ThrowReportFromStartDateToEndDateMoreThanOneMonthsException();
                    break;
                case EnumTimeIntervalType.Daily:
                    // 暂时去掉限制
                    //if (search.startDate.AddMonths(3) < search.endDate)
                    //    ExceptionHelper.ThrowReportDaysFromStartDateToEndDateMoreThanMonthsException(3);
                    break;
                case EnumTimeIntervalType.Weekly:
                    //double timezoneOffSet = CommonHelper.GetTimeZoneOffSet();
                    ////Local Time
                    //DateTime startDate = DateTimeHelper.UTCDateTimeToLocalDateTime(search.startDate, _currentSite, _operatingOperator, timezoneOffSet);
                    ////Local Time
                    //DateTime endDate = DateTimeHelper.UTCDateTimeToLocalDateTime(search.endDate, _currentSite, _operatingOperator, timezoneOffSet);

                    //DateTime firstWeekSunday = startDate.AddDays((int)startDate.DayOfWeek);

                    //暂时去掉限制
                    //if (((TimeSpan)(endDate - firstWeekSunday)).TotalDays >= 56)
                    //{
                    //    ExceptionHelper.ThrowReportWeeksFromStartDateToEndDateMoreThanTheMaxValueException();
                    break;
                case EnumTimeIntervalType.Monthly:
                    //暂时去掉限制
                    //if (search.endDate.Year * 12 + search.endDate.Month - search.startDate.Year * 12 - search.startDate.Month + 1 > 6)
                    //    ExceptionHelper.ThrowReportMonthsFromStartDateToEndDateMoreThanTheMaxValueException();
                    break;
                case EnumTimeIntervalType.Distribution24_7Hour:
                    //暂时去掉限制
                    //CheckDate(search.startDate, search.endDate);
                    break;
                case EnumTimeIntervalType.Distribution48HalfHour:
                    //暂时去掉限制
                    //CheckDate(search.startDate, search.endDate);
                    break;
            }
        }

        //check the logic of start date time and end date time
        private static void CheckDate(DateTime startDate, DateTime endDate)
        {
            if (startDate > endDate)
            {
                ExceptionHelper.ThrowReportStartDateGreaterThanEndDateException();
            }

            int monthLimit = WebConfigHelper.GetConfigSetting_LiveChatExportTimeRangeMonthCount();

            if (endDate > startDate.AddMonths(monthLimit))
            {
                ExceptionHelper.ThrowReportDaysFromStartDateToEndDateMoreThanMonthsException(monthLimit);
            }

        }

        #region ExportReport

        private static Stream GetStream(DataTable table)
        {
            StringBuilder sb = new StringBuilder();
            if (table != null && table.Columns.Count > 0 && table.Rows.Count > 0)
            {
                foreach (DataRow item in table.Rows)
                {
                    for (int i = 0; i < table.Columns.Count; i++)
                    {
                        if (i > 0)
                        {
                            sb.Append(",");
                        }
                        if (item[i] != null)
                        {
                            sb.Append("\"").Append(item[i].ToString().Replace("\"", "\"\"")).Append("\"");
                        }
                    }
                    sb.Append("\n");
                }
            }
            MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(sb.ToString()));
            return stream;
        }
        public static string SaveReport(SearchCriteria search, NewExportCSVData exportdata)
        {
            using (Stream sm = GetStream(exportdata.source))
            {
                int buffSize = (int)sm.Length;
                byte[] buff = new byte[buffSize];
                sm.Read(buff, 0, buffSize);
                int siteId = search.siteId;
                string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "UploadedFiles", siteId.ToString());
                if (!Directory.Exists(path))
                    Directory.CreateDirectory(path);
                using (FileStream fs = new FileStream(string.Format("{0}\\{1}.csv",path, exportdata.name), FileMode.Create))
                {
                    using (BinaryWriter bw = new BinaryWriter(fs))
                    {
                        bw.Write(buff);
                        //string fullUrl = RequestHelper.GetRequest_Url_AbsoluteUri();
                        //string masterUrl = fullUrl.Substring(0, fullUrl.ToLower().IndexOf("/api/"));
                        //string currFile = fs.Name.Substring(path.ToLower().IndexOf("botapi") + 6);
                        //string url = string.Format("{0}{1}", masterUrl, currFile.Replace("\\", "/"));
                        //return url.Split(new string[] { "/" }, StringSplitOptions.RemoveEmptyEntries).LastOrDefault(); 
                        return fs.Name;
                    }
                }
            }
        }
        #endregion

    }
}
